package l1j.server.server.serverpackets;

import java.util.Calendar;
import java.util.Iterator;
import java.util.TimeZone;
import java.util.logging.Logger;

import l1j.server.configure.Config;
import l1j.server.server.Opcodes;
import l1j.server.server.model.L1World;
import l1j.server.server.model.Instance.L1PcInstance;
import l1j.server.server.templates.L1Account;

public class S_PacketBox extends ServerBasePacket {
	private static final String S_PACKETBOX = "[S] S_PacketBox";

	@SuppressWarnings("unused")
	private static Logger _log = Logger.getLogger(S_PacketBox.class.getName());

	private byte[] _byte = null;

	// 1:Kent 2:Orc 3:WW 4:Giran 5:Heine 6:Dwarf 7:Aden 8:Diad 9:성명 9 ...
	/** C(id) H(? ): %s의 공성전이 시작되었습니다. */
	public static final int MSG_WAR_BEGIN = 0;

	/** C(id) H(? ): %s의 공성전이 종료했습니다. */
	public static final int MSG_WAR_END = 1;

	/** C(id) H(? ): %s의 공성전이 진행중입니다. */
	public static final int MSG_WAR_GOING = 2;

	/** -: 성의 주도권을 잡았습니다. (음악이 바뀐다) */
	public static final int MSG_WAR_INITIATIVE = 3;

	/** -: 성을 점거했습니다. */
	public static final int MSG_WAR_OCCUPY = 4;

	/** ? : 결투가 끝났습니다. (음악이 바뀐다) */
	public static final int MSG_DUEL = 5;

	/** C(count): SMS의 송신에 실패했습니다. / 전부%d건송신되었습니다. */
	public static final int MSG_SMS_SENT = 6;

	/** -: 축복안, 2명은 부부로서 연결되었습니다. (음악이 바뀐다) */
	public static final int MSG_MARRIED = 9;

	/** C(weight): 중량(30 단계) */
	public static final int WEIGHT = 10;

	/** C(food): 만복도(30 단계) */
	public static final int FOOD = 11;

	/** C(0) C(level): 이 아이템은%d레벨 이하만 사용할 수 있습니다. (0~49이외는 표시되지 않는다) */
	public static final int MSG_LEVEL_OVER = 12;

	/** UB정보 HTML */
	public static final int HTML_UB = 14;

	/**
	 * C(id)<br>
	 * 1:몸에 담겨져 있던 정령의 힘이 공기안에 녹아 가는 것을 느꼈습니다. <br>
	 * 2:몸의 구석구석에 화의 정령력이 스며들어 옵니다. <br>
	 * 3:몸의 구석구석에 물의 정령력이 스며들어 옵니다. <br>
	 * 4:몸의 구석구석에 바람의 정령력이 스며들어 옵니다. <br>
	 * 5:몸의 구석구석에 땅의 정령력이 스며들어 옵니다. <br>
	 */
	public static final int MSG_ELF = 15;

	/** C(count) S(name)...: 차단 리스트 복수 추가 */
	public static final int ADD_EXCLUDE2 = 17;

	/** S(name): 차단 리스트 추가 */
	public static final int ADD_EXCLUDE = 18;

	/** S(name): 차단 해제 */
	public static final int REM_EXCLUDE = 19;

	/** 스킬 아이콘 */
	public static final int ICONS1 = 20;

	/** 스킬 아이콘 */
	public static final int ICONS2 = 21;

	/** 아우라계의 스킬 아이콘 */
	public static final int ICON_AURA = 22;

	/** S(name): 타운 리더에게%s가 선택되었습니다. */
	public static final int MSG_TOWN_LEADER = 23;

	/**
	 * D(혈맹원수) (S(혈원이름) C(혈원계급)) 혈맹원 갱신이 된 상태에서의 /혈맹.
	 */
	public static final int PLEDGE_TWO = 24;

	/**
	 * D(혈맹원이름) C(랭크) 혈맹에 추가된 인원이 있을때 보내주는 패킷
	 */
	public static final int PLEDGE_REFRESH_PLUS = 25;

	/**
	 * D(혈맹원이름) C(랭크) 혈맹에 삭제된 인원이 있을때 보내주는 패킷
	 */
	public static final int PLEDGE_REFRESH_MINUS = 26;

	/**
	 * C(id): 당신의 랭크가%s로 변경되었습니다. (1-견습 2-일반 3-수호기사)
	 */
	public static final int MSG_RANK_CHANGED = 27;

	/**
	 * D(혈맹원수) (S(혈원이름) C(혈원계급)) 혈맹원 갱신이 안된 상태에서의 /혈맹.
	 */
	public static final int PLEDGE_ONE = 29;

	/** D(?) S(name) S(clanname): %s혈맹의%s가 라스타바드군을 치웠습니다. */
	public static final int MSG_WIN_LASTAVARD = 30;

	/** -: \f1기분이 좋아졌습니다. */
	public static final int MSG_FEEL_GOOD = 31;

	/** 불명.C_30 패킷이 난다 */
	public static final int SOMETHING1 = 33;

	/** H(time): 블루 일부의 아이콘이 표시된다. */
	public static final int ICON_BLUEPOTION = 34;

	/** H(time): 변신의 아이콘이 표시된다. */
	public static final int ICON_POLYMORPH = 35;

	/** H(time): 채팅 금지의 아이콘이 표시된다. */
	public static final int ICON_CHATBAN = 36;

	/** 불명. C_7 패킷이 난다. C_7은 애완동물의 메뉴를 열었을 때에도 난다. */
	public static final int SOMETHING2 = 37;

	/** 혈맹 정보의 HTML가 표시된다 */
	public static final int HTML_CLAN1 = 38;

	/** H(time): 이뮤의 아이콘이 표시된다 */
	public static final int ICON_I2H = 40;

	/** 캐릭터의 게임 옵션, 쇼트 컷 정보등을 보낸다 */
	public static final int CHARACTER_CONFIG = 41;

	/** 캐릭터 선택 화면으로 돌아간다 */
	public static final int LOGOUT = 42;

	/** 전투중에 재시작 할 수 없습니다. */
	public static final int MSG_CANT_LOGOUT = 43;

	/**
	 * C(count) D(time) S(name) S(info):<br>
	 * [CALL] 버튼이 붙은 윈도우가 표시된다. 이름을 더블 클릭 하면(자) C_RequestWho가 날아, 클라이언트의 폴더에
	 * bot_list.txt가 생성된다.이름을 선택해+키를 누르면(자) 새로운 윈도우가 열린다.
	 */
	public static final int CALL_SOMETHING = 45;

	/**
	 * C(id): 배틀 콜롯세움, 카오스 대전이―<br>
	 * id - 1:개시합니다 2:삭제되었던 3:종료합니다
	 */
	public static final int MSG_COLOSSEUM = 49;

	/** 혈맹 정보의 HTML */
	public static final int HTML_CLAN2 = 51;

	/** 요리 윈도우를 연다 */
	public static final int COOK_WINDOW = 52;

	/** C(type) H(time): 요리 아이콘이 표시된다 */
	public static final int ICON_COOKING = 53;

	/** 물고기찌 흔들림포시 */
	public static final int FISHING = 55;

	/** 아이콘 삭제 */
	public static final int DEL_ICON = 59;

	/** 드래곤 진주 */
	public static final int DRAGONPERL = 60;

	/** 계정 시간 type:예약결제 time:시간 */
	public static final int ACCOUNT_TIME = 61;

	/** 동맹 목록 */
	public static final int ALLIANCE_LIST = 62;

	/** 미니게임 : 5,4,3,2,1 카운트 */
	public static final int MINIGAME_START_COUNT = 64;

	/** 미니게임 : 타임(0:00시작) */
	public static final int MINIGAME_START_TIME = 65;

	/** 미니게임 : 게임자 리스트 */
	public static final int MINIGAME_LIST = 66;

	/** 미니게임 : 잠시 후 마을로 이동됩니다(10초 음) **/
	public static final int MINIGAME_10SECOND_COUNT = 69;

	/** 미니게임 : 종료 */
	public static final int MINIGAME_END = 70;

	/** 미니게임 : 타임 */
	public static final int MINIGAME_TIME = 71;

	/** 미니게임 : 타임삭제 */
	public static final int MINIGAME_TIME_CLEAR = 72;

	/** 팔을 다쳐 공격 능력이 하락합니다. */
	public static final int DAMAGE_DOWN = 74;

	/** 용기사 : 약점 노출 */
	public static final int SPOT = 75;

	/**
	 * 공성전이 시작되었습니다. 78 성을 소유하고 있는 혈맹은 다음과 같습니다.
	 */

	/**
	 * 공성전이 종료되었습니다. 79 성을 소유하고 있는 혈맹은 다음과 같습니다.
	 */

	/**
	 * 공성전이 진행중입니다. 80 성을 소유하고 있는 혈맹은 다음과 같습니다.
	 */

	/** 아인하사드 버프 */
	public static final int AINHASAD = 82;

	/** 그린메시지 */
	public static final int GREEN_MESSAGE = 84;

	/** 드래곤 에메랄드 */
	public static final int EMERALD_EVA = 86;

	/**
	 * 우호도 UI 표시 + 욕망의 동굴 - 그림자 신전
	 */
	public static final int KARMA = 87;

	/** 닷지 포인트 */
	public static final int LOGIN_UNKNOWN1 = 88;

	/** 혈흔 */
	public static final int DRAGONBLOOD = 100;

	/** 변경된 닷지 포인트 표시 */
	public static final int LOGIN_UNKNOWN2 = 101;

	/** 드래곤 메뉴 */
	public static final int DRAGONMENU = 102;

	/** 파티 멤버 */
	public static final int UPDATE_OLD_PART_MEMBER = 104;

	/** 파티 멤버 갱신 */
	public static final int PATRY_UPDATE_MEMBER = 105;

	/** 파티 리더 위임 */
	public static final int PATRY_SET_MASTER = 106;

	/** 파티 정보 갱신 */
	public static final int PATRY_MEMBERS = 110;

	/** 바포 시스템 */
	public static final int BAPO = 114;

	/** EXP 포션 */
	public static final int EXP_POTION3 = 9278;

	/** EXP 포션 */
	public static final int EXP_POTION2 = 9279;

	public static final int YELLOW_MESSAGE = 0; // 못찾음

	public S_PacketBox(int subCode) {
		writeC(Opcodes.S_OPCODE_PACKETBOX);
		writeC(subCode);

		switch (subCode) {
		case MSG_WAR_INITIATIVE:
		case MSG_WAR_OCCUPY:
		case MSG_MARRIED:
		case MSG_FEEL_GOOD:
		case MSG_CANT_LOGOUT:
		case LOGOUT:
			break;
		case FISHING:
		case MINIGAME_START_TIME:
		case MINIGAME_TIME_CLEAR:
			break;
		case CALL_SOMETHING:
			callSomething();
			break;
		case DEL_ICON:
			writeH(0);
			break;
		case ICON_AURA:
			writeC(0x98);
			writeC(0);
			writeC(0);
			writeC(0);
			writeC(0);
			writeC(0);
			break;
		case MINIGAME_10SECOND_COUNT:
			writeC(10);
			writeC(109);
			writeC(85);
			writeC(208);
			writeC(2);
			writeC(220);
			break;
		case MINIGAME_END:
			writeC(147);
			writeC(92);
			writeC(151);
			writeC(220);
			writeC(42);
			writeC(74);
			break;
		case MINIGAME_START_COUNT:
			writeC(5);
			writeC(129);
			writeC(252);
			writeC(125);
			writeC(110);
			writeC(17);
			break;
		default:
			break;
		}
	}

	public S_PacketBox(int subCode, int value) {
		writeC(Opcodes.S_OPCODE_PACKETBOX);
		writeC(subCode);

		switch (subCode) {
		case ICON_BLUEPOTION:
		case ICON_CHATBAN:
		case ICON_I2H:
		case ICON_POLYMORPH:
		case MINIGAME_TIME:
		case LOGIN_UNKNOWN1:
			writeH(value); // time
			break;
		case MSG_WAR_BEGIN:
		case MSG_WAR_END:
		case MSG_WAR_GOING:
			writeC(value); // castle id
			writeH(0); // ?
			break;
		case MSG_SMS_SENT:
		case WEIGHT:
		case FOOD:
		case LOGIN_UNKNOWN2:
			writeC(value);
			break;
		case MSG_ELF:
		case MSG_RANK_CHANGED:
		case MSG_COLOSSEUM:
		case SPOT:
			writeC(value); // msg id
			break;
		case MSG_LEVEL_OVER:
			writeC(0); // ?
			writeC(value); // 0-49이외는 표시되지 않는다
			break;
		case COOK_WINDOW:
			writeC(0xdb); // ?
			writeC(0x31);
			writeC(0xdf);
			writeC(0x02);
			writeC(0x01);
			writeC(value); // level
			break;
		case AINHASAD:
			value /= 10000;
			writeD(value);// % 수치 1~200
		default:
			break;
		}
	}

	public S_PacketBox(int subCode, int type, int time) {
		writeC(Opcodes.S_OPCODE_PACKETBOX);
		writeC(subCode);

		switch (subCode) {
		case DRAGONBLOOD:
			writeC(type);
			writeD(time);
			break;
		case EMERALD_EVA:
			writeC(0x70);
			writeC(0x01);
			writeC(type);
			writeD(time);
			break;
		case DRAGONPERL:
			writeC(time);
			writeC(type);
			break;
		case EXP_POTION2:
			writeC(time);
			writeC(type);
			break;
		case EXP_POTION3:
			writeC(time);
			writeC(type);
			break;
		case ACCOUNT_TIME:
			writeD(time);
			writeC(type);
		case ICON_COOKING:
			if (type != 7) {
				writeC(0x0c);
				writeC(0x0c);
				writeC(0x0c);
				writeC(0x12);
				writeC(0x0c);
				writeC(0x09);
				writeC(0x00);
				writeC(0x00);
				writeC(type);
				writeC(0x24);
				writeH(time);
				writeH(0x00);
			} else {
				writeC(0x0c);
				writeC(0x0c);
				writeC(0x0c);
				writeC(0x12);
				writeC(0x0c);
				writeC(0x09);
				writeC(0xc8);
				writeC(0x00);
				writeC(type);
				writeC(0x26);
				writeH(time);
				writeC(0x3e);
				writeC(0x87);
			}
			break;
		case ICON_AURA:
			writeC(0xdd);
			writeH(time);
			writeC(type);
			break;
		case MSG_DUEL:
			writeD(type);
			writeD(time);
			break;
		default:
			break;
		}
	}

	public S_PacketBox(int subCode, String name) {

		writeC(Opcodes.S_OPCODE_PACKETBOX);
		writeC(subCode);

		switch (subCode) {
		case ADD_EXCLUDE:
		case REM_EXCLUDE:
		case MSG_TOWN_LEADER:
			writeS(name);
			break;
		case GREEN_MESSAGE:
			writeC(2);
			writeS(name);
			break;
		case YELLOW_MESSAGE:
			break;
		default:
			break;
		}
	}
	
	

	public S_PacketBox(int subCode, int id, String name, String clanName) {
		writeC(Opcodes.S_OPCODE_PACKETBOX);
		writeC(subCode);

		switch (subCode) {
		case MSG_WIN_LASTAVARD:
			writeD(id); // 크란 ID인가 무엇인가?
			writeS(name);
			writeS(clanName);
			break;
		default:
			break;
		}
	}

	public S_PacketBox(int subCode, Object[] names) {
		writeC(Opcodes.S_OPCODE_PACKETBOX);
		writeC(subCode);

		switch (subCode) {
		case ADD_EXCLUDE2:
			writeC(names.length);
			for (Object name : names) {
				writeS(name.toString());
			}
			break;
		default:
			break;
		}
	}

	private void callSomething() {
		Iterator<L1PcInstance> itr = L1World.getInstance().getAllPlayers()
				.iterator();

		writeC(L1World.getInstance().getAllPlayers().size());

		while (itr.hasNext()) {
			L1PcInstance pc = itr.next();
			L1Account acc = L1Account.findByName(pc.getAccountName());

			// 時間情報 とりあえずログイン時間を入れてみる
			if (acc == null) {
				writeD(0);
			} else {
				Calendar cal = Calendar.getInstance(TimeZone
						.getTimeZone(Config.TIME_ZONE));
				long lastactive = acc.getLastActivatedAt().getTime();
				cal.setTimeInMillis(lastactive);
				cal.set(Calendar.YEAR, 1970);
				int time = (int) (cal.getTimeInMillis() / 1000);
				writeD(time); // JST 1970 1/1 09:00 が基準
			}

			// キャラ情報
			writeS(pc.getName()); // 半角12字まで
			writeS(pc.getClanname()); // []内に表示される文字列。半角12字まで
		}
	}

	@Override
	public byte[] getContent() {
		if (_byte == null) {
			_byte = getBytes();
		}

		return _byte;
	}

	@Override
	public String getType() {
		return S_PACKETBOX;
	}
}